package com.zcm.modules.cxf.utils;


import com.zcm.common.utils.SpringContextHolder;
import com.zcm.modules.cxf.entity.CxfSession;
import com.zcm.modules.cxf.entity.HeaderEntity;
import com.zcm.modules.cxf.service.CxfSessionService;
import org.apache.cxf.binding.soap.HeaderUtil;
import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.DigestUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.xml.namespace.QName;
import java.security.MessageDigest;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

public class WebServiceHeaderUtil {
    public static DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    public static String DEFAULT_ENCODING = "UTF-8";
    public static int MAX_SALT = 100;//最大盐值MAX_SALT-1
    public static int DEFALUT_SALT = 50;//当盐值为0时，取默认值
    public static QName REQUEST_HEADER_QNAME = new QName("header", "http://sechemas.services.cxf.modules.zcm.com/header/");
    public static QName RESPONSE_HEADER_QNAME = new QName("header", "http://sechemas.services.cxf.modules.zcm.com/header/");
    /*--------------标签名----------------------------*/
    public static String REQUEST_HEADER_TAGETNAME_ID = "id";
    public static String REQUEST_HEADER_TAGETNAME_TIME = "time";
    public static String REQUEST_HEADER_TAGETNAME_CODE = "code";
    public static String RESPONSE_HEADER_TAGETNAME_ID = "id";
    public static String RESPONSE_HEADER_TAGETNAME_TIME = "time";
    public static String RESPONSE_HEADER_TAGETNAME_CODE = "code";

    private static CxfSessionService cxfSessionService = SpringContextHolder.getBean(CxfSessionService.class);
    /**
     * MD5密码加密
     * @param password
     * @return
     */
    public static String getMD5(String password) {
        String md5 = null;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] array = md.digest(password.getBytes("utf-8"));
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < array.length; i++) {
                sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100)
                        .toUpperCase().substring(1, 3));
            }
            md5 = sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return md5;

    }
    /**
     * 创造请求头信息
     *
     * @return 返回构建好的xml
     */
    public static SoapHeader createRquestHeader() {
        SoapHeader header = null;
        try {
            String reqeustId = UUID.randomUUID().toString();
            String requestTime = DATE_FORMAT.format(new Date());
            String requestCode = createCode(reqeustId, requestTime);
            Document doc = DOMUtils.createDocument();
            Element root = doc.createElement("dd:header");
            root.setAttribute("xmlns:dd", "http://sechemas.xml.dd.com/header/");
            Element idEle = doc.createElement(REQUEST_HEADER_TAGETNAME_ID);
            idEle.setTextContent(reqeustId);
            Element timeEle = doc.createElement(REQUEST_HEADER_TAGETNAME_TIME);
            timeEle.setTextContent(requestTime);
            Element codeEle = doc.createElement(REQUEST_HEADER_TAGETNAME_CODE);
            codeEle.setTextContent(requestCode);
            root.appendChild(idEle);
            root.appendChild(timeEle);
            root.appendChild(codeEle);
            header = new SoapHeader(REQUEST_HEADER_QNAME, root);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            return header;
        }
    }

    public static SoapHeader createResponsetHeader() {
        SoapHeader header = null;
        try {
            String reqeustId = UUID.randomUUID().toString();
            String reponseTime = DATE_FORMAT.format(new Date());
            String reponseCode = createCode(reqeustId, reponseTime);
            Document doc = DOMUtils.createDocument();
            Element root = doc.createElement("dd:header");
            root.setAttribute("xmlns:dd", "http://sechemas.services.cxf.modules.zcm.com/header");
            Element idEle = doc.createElement(RESPONSE_HEADER_TAGETNAME_ID);
            idEle.setTextContent(reqeustId);
            Element timeEle = doc.createElement(RESPONSE_HEADER_TAGETNAME_TIME);
            timeEle.setTextContent(reponseTime);
            Element codeEle = doc.createElement(RESPONSE_HEADER_TAGETNAME_CODE);
            codeEle.setTextContent(reponseCode);
            root.appendChild(idEle);
            root.appendChild(timeEle);
            root.appendChild(codeEle);
            header = new SoapHeader(RESPONSE_HEADER_QNAME, root);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            return header;
        }
    }

    public static String createCode(String id, String time) {
        String src = String.format("id=%s&time=%s",id.trim(),time.trim());
        String retStr = getMD5(src).replaceAll("[\\D]+", "");
        if(retStr.length() == 0){
            retStr = "=";
        }
        return retStr;
    }

    public static void validateHeaderWithoutSession(HeaderEntity header) {
        Assert.notNull(header.getId(), "id不能为Null");
        Assert.notNull(header.getCode(), "time不能为Null");
        Assert.notNull(header.getTime(), "code不能为Null");
        if( !header.getCode().equals(createCode(header.getId(), header.getTime()))){
            throw new Fault(new Exception("没有检查到请求头"));
        }
    }

    public static void validateHeader(HeaderEntity header) {
        validateHeaderWithoutSession(header);
        validateSession(header.getSessionId());
    }
    public static void validateSession(String sessionId) {
        Assert.notNull(sessionId, "sessionId不能为Null");
        if(cxfSessionService.getBySessionId(sessionId)==null){
            throw new Fault(new Exception("会话不存在！"));
        }
    }
}